package com.qws.xprinter.flutter_xprinter.device

import android.os.Handler
import android.os.Looper
import android.util.Log
import com.jeremyliao.liveeventbus.LiveEventBus
import com.qws.xprinter.flutter_xprinter.App
import com.qws.xprinter.flutter_xprinter.bean.ConnType
import com.qws.xprinter.flutter_xprinter.queue.PrintTaskQueue
import com.qws.xprinter.flutter_xprinter.utils.Constant
import net.posprinter.IConnectListener
import net.posprinter.IDeviceConnection
import net.posprinter.POSConnect

class XPrinter(private val connType: Int, private val address: String) : QwsPrinter {
    private var connection: IDeviceConnection? = null
    private var taskQueue: PrintTaskQueue = PrintTaskQueue()
    private val handler: Handler = Handler(Looper.getMainLooper())
    private val closeRunnable = Runnable {
        disconnect()
    }

    private val connectListener = IConnectListener { code, connInfo, msg ->
        App.get().channel?.invokeMethod(
            "connect",
            mapOf("code" to code, "address" to connInfo, "msg" to msg)
        )
        when (code) {
            POSConnect.CONNECT_SUCCESS -> {
                LiveEventBus.get<Boolean>(Constant.EVENT_CONNECT_STATUS).post(true)
                taskQueue.resume()
                Log.d("XPrinter", "CONNECT_SUCCESS")
            }

            POSConnect.CONNECT_FAIL, POSConnect.CONNECT_INTERRUPT, POSConnect.USB_DETACHED -> {
                taskQueue.pause()
                disconnect()
                connect()
                LiveEventBus.get<Boolean>(Constant.EVENT_CONNECT_STATUS).post(false)
                Log.d("XPrinter", "CONNECT_FAIL")
            }

            POSConnect.SEND_FAIL -> {
                taskQueue.pause()
            }

            POSConnect.USB_ATTACHED -> {
            }
        }
    }

    init {
        taskQueue.setPrintQueueListener(object : PrintTaskQueue.PrintQueueListener {

            override fun onQueueEmpty() {
                handler.postDelayed(closeRunnable, 1000 * 60 * 3)
            }
        })
    }

    override fun connect() {
        connection = when (connType) {
            ConnType.USB.ordinal -> {
                connectUSB(address)
            }

            ConnType.BLUETOOTH.ordinal -> {
                connectBt(address)
            }

            ConnType.NET.ordinal -> {
                connectNet(address)
            }

            else -> {
                null
            }
        }
    }

    override fun disconnect() {
        Log.d("XPrinter", "disconnect")
        connection?.close()
    }

    override fun sendPrintTask(bytes: List<Int>) {
        handler.removeCallbacks(closeRunnable)
        taskQueue.addTask {
            if (connection != null && connection?.isConnect == true) {
                Log.d("XPrinter", "send print task")
                write(bytes)
            } else {
                Log.d("XPrinter", "is not connect")
                taskQueue.addTask { write(bytes) }
            }
            
        }
        // 先检查连接状态，如果未连接再进行连接
        // 避免先断开再连接导致的任务丢失
        if (connection == null || !isConnected()) {
            connect()
        } else {
            // 已连接状态下直接恢复队列执行
            taskQueue.resume()
        }
    }

    private fun write(bytes: List<Int>) {
        connection?.let {
            it.sendData(byteArrayOf(27, 64))
            it.sendData(bytes.toTypedArray().toByteArray())
        }
    }

    private fun connectUSB(pathName: String): IDeviceConnection {
        val connect = POSConnect.createDevice(POSConnect.DEVICE_TYPE_USB)
        connect.connect(pathName, connectListener)
        return connect
    }

    private fun connectNet(ipAddress: String): IDeviceConnection {
        val connect = POSConnect.createDevice(POSConnect.DEVICE_TYPE_ETHERNET)
        connect.connect(ipAddress, connectListener)
        return connect
    }

    private fun connectBt(macAddress: String): IDeviceConnection {
        val connect = POSConnect.createDevice(POSConnect.DEVICE_TYPE_BLUETOOTH)
        connect.connect(macAddress, connectListener)
        return connect
    }
    
    // 检查当前连接状态
    private fun isConnected(): Boolean {
        return connection?.let {
            try {
                // 尝试获取连接状态
                it.isConnect
            } catch (e: Exception) {
                Log.e("XPrinter", "检查连接状态异常: ${e.message}")
                false
            }
        } ?: false
    }
}